package com.isecommerce.framework.util;

import java.io.*;
import java.util.*;

/** Log Writer <p> 
* Record the log for a method action. <br>
*
* @author  WROX
**/

public class LogWriter
{
	   /** NONE-LOG Log-level code 0 */
	   public static final int NONE = 0;
	   
	   /** Error Message Log-level code 1 */
	   public static final int ERROR = 1;
	   
	   /** Message Info Log-level code 2 */
	   public static final int INFO = 2;
	   
	   /** Debug Message Log-level code 3 */
	   public static final int DEBUG = 3;
	   
	   private static LogWriter refObject;
	   
	   private static final String ERROR_TEXT = "ERROR";
	   private static final String INFO_TEXT = "INFO";
	   private static final String DEBUG_TEXT = "DEBUG";
	    
	   private PrintWriter pw;
	   private String owner;
	   private int logLevel;
	   
	   
	   /**
	    * Singleton Instance
	    */
	   public static LogWriter getLogWriterInstance(String owner, int logLevel, PrintWriter pw){
		   
		   if(refObject == null) refObject = new LogWriter(owner, logLevel, pw);
		   
		   return refObject;
	   }
	   
	   /**
	    * Singleton Instance
	    */
	   public static LogWriter getLogWriterInstance(String owner, int logLevel){
		   
		   if(refObject == null) refObject = new LogWriter(owner, logLevel);
		   
		   return refObject;
	   }
	   
	   /**
	    * Blocking clone method
	    */
	   public Object clone() throws CloneNotSupportedException
	   {
		   throw new CloneNotSupportedException();
	   }	   
	   
	   /** Constructor type 1 for LogWriter<p>   
	   * @param owner Common string apply for all log message.
	   * @param logLevel Set the log level.
	   * @param pw The PrintWriter to record log message.
	   */ 
	   private LogWriter(String owner, int logLevel, PrintWriter pw)
	   {
	      this.pw = pw;
	      this.owner = owner;
	      this.logLevel = logLevel;
	   }
	
	   /** Constructor type 2 for LogWriter<p>   
	   * @param owner Common string apply for all log message.
	   * @param logLevel Set the log level.   
	   */  	
	   private LogWriter(String owner, int logLevel)
	   {
	      this(owner, logLevel, null);
	   }
	   
	   /** Get current log level.<p> */ 
	   public int getLogLevel()
	   {
	      return logLevel;
	   }
	    
	   /** Get the PrintWriter.<p> */	
	   public PrintWriter getPrintWriter()
	   {
	      return pw;
	   }
	    
	   /** Set the log level.<p> 
	   * @param logLevel Set the log level.
	   */	
	   public void setLogLevel(int logLevel)
	   {
	      this.logLevel = logLevel;
	   }
	   
	   /** Set the PrintWriter.<p> 
	   * @param pw PrintWriter object.
	   */    
	   public void setPrintWriter(PrintWriter pw)
	   {
	      this.pw = pw;
	   }
	   
	   /** Set the Owner.<p> 
	   * @param owner owner object.
	   */    
	   public void setOwner(String owner)
	   {
	      this.owner = owner;
	   }
	   
	   /** Recording the log file, if log-level is lower or equal than current level then write log into PrintWriter.<p>
	   * @param msg The message.
	   * @param serverityLevel The level of messages.
	   */	
	   public void logPureText(String msg, int severityLevel)
	   {
	      if (pw != null)
	      {
	         if (severityLevel <= logLevel)
	         {
	            pw.println(msg);
	         }
	      }
	   }
	    
	   /** Recording the log file, if log-level is lower or equal than current level then write log into PrintWriter.<p>
	   * @param msg The message.
	   * @param serverityLevel The level of messages.
	   */	
	   public void log(String msg, int severityLevel)
	   {   
		      if (pw != null)
		      {
		    	 	
		         if (severityLevel <= logLevel)
		         { 
		            pw.println("[" + new Date() + "]  " +
		            getSeverityString(severityLevel) + ": " +
		            owner + ": " + msg);
		         }
		      }
	   }
	
	   /** Recording the log file, if log-level is lower or equal than current level then write log into PrintWriter. And also write the log of traced Throwable.<p>
	   * @param t Throwable that write into message.
	   * @param msg The message.
	   * @param serverityLevel The level of messages.
	   */	 
	   public void log(Throwable t, String msg, int severityLevel)
	   {
	      log(msg + " : " + toTrace(t), severityLevel);
	   }
	   
	   /** Get the serverity string according to log-level code.<p> */    
	   private String getSeverityString(int severityLevel)
	   {
	      switch (severityLevel)
	      {
	         case ERROR:
	            return ERROR_TEXT;
	         case INFO:
	            return INFO_TEXT;
	         case DEBUG:
	            return DEBUG_TEXT;
	         default:
	            return "Unknown";
	      }
	   }
	    
	   /** Tracing given Throwable.<p> 
	   * @param e Given Throwable.
	   */	
	   private String toTrace(Throwable e)
	   {
	      StringWriter sw = new StringWriter();
	      PrintWriter pw = new PrintWriter(sw);
	      e.printStackTrace(pw);
	      pw.flush();
	      return sw.toString();
	   }
	}